package web.protocols.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import domain.entities.*;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.ConcurrencyFailureException;
import services.*;
import services.exceptions.ExistentInvestigadorProtocoloCentroException;
import services.exceptions.InexistentProtocoloCentroException;
import services.exceptions.NoProtocoloCompromisopaisSelectedException;

import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: scamisay
 * Date: 11/2/12
 * Time: 12:28 PM
 * To change this template use File | Settings | File Templates.
 */
@Namespace("/Protocols/SiteStaffSelection")
public class SiteStaffSelectionController extends ActionSupport implements ModelDriven {

    private InvestigadorProtocoloCentro investigadorProtocoloCentro;
    private InvestigadorProtocoloCentroService investigadorProtocoloCentroService;
    private ProtocoloCentroService protocoloCentroService;
    private ProtocolCRUDService protocolCRUDService;
    private List<InvestigadorProtocoloCentro> list;
    private List<Centro> sites;
    private List<Role> sitesRoles = new ArrayList<Role>();
    private RoleCRUDService roleCRUDService;
    private String errorMessage;
    private CdaService cdaService;
    private List<CdaMolecula> cdaMoleculas;
    private List<Decision> siteStaffRequireSafety;
    private List<Involucrado> ECMemberCandidates;

    @Autowired
    public SiteStaffSelectionController(InvestigadorProtocoloCentroService investigadorProtocoloCentroService, ProtocoloCentroService protocoloCentroService, ProtocolCRUDService protocolCRUDService, RoleCRUDService roleCRUDService, CdaService cdaService){

        this.investigadorProtocoloCentroService = investigadorProtocoloCentroService;
        this.protocoloCentroService = protocoloCentroService;
        this.protocolCRUDService = protocolCRUDService;
        this.roleCRUDService = roleCRUDService;
        this.cdaService = cdaService;
        investigadorProtocoloCentro=new InvestigadorProtocoloCentro();
        siteStaffRequireSafety = new ArrayList<Decision>();
    }

    @Override
    public InvestigadorProtocoloCentro getModel() {
        return investigadorProtocoloCentro;
    }

    public void findByInvolucradoId(Integer id) {
            cdaMoleculas = cdaService.findByInvolucradoId(id);
    }

    @Action(value="main", results={
            @Result(name="success", location="/protocols.siteStaffSelection.tiles", type="tiles")
    })
    public String execute() throws NoProtocoloCompromisopaisSelectedException {
        ProtocoloCompromisopais protocoloCompromisopais = protocolCRUDService.recoverProtocoloCompromisopais();
        list = investigadorProtocoloCentroService.findAllBy(protocoloCompromisopais);
        sites = protocoloCentroService.getSitesByProtocoloCompromisoPaisAndIPCs(
                protocoloCompromisopais,
                list);
        if(investigadorProtocoloCentro != null && !investigadorProtocoloCentro.isNew()){
            investigadorProtocoloCentro = investigadorProtocoloCentroService.findById(investigadorProtocoloCentro.getId());
            findByInvolucradoId(investigadorProtocoloCentro.getPrincipalInvestigator().getId());
            _prepairNullSiteStaffRoles(investigadorProtocoloCentro);
            sites.add(investigadorProtocoloCentro.getProtocoloCentro().getCentro());
            ECMemberCandidates = populateECMemberCandidates(investigadorProtocoloCentro);
        }else{
            investigadorProtocoloCentro = new InvestigadorProtocoloCentro();
        }
        return SUCCESS;
    }

    private List<Involucrado> populateECMemberCandidates(InvestigadorProtocoloCentro investigadorProtocoloCentro) {
        Set<Involucrado> set = new HashSet<Involucrado>(0);
        set.add(investigadorProtocoloCentro.getPrincipalInvestigator());
        if(investigadorProtocoloCentro.getSubInvestigator() != null){
            set.add(investigadorProtocoloCentro.getSubInvestigator());
        }
        for(RoleNameProtocoloCompromisoPais rnpcp:investigadorProtocoloCentro.getSiteStaff()){
            if(rnpcp.getInvolucrado() != null){
                set.add(rnpcp.getInvolucrado());
            }
        }
        return new ArrayList<Involucrado>(set);
    }

    @Action(value="save", results={
            @Result(name="success",location="main", type="redirectAction"),
            @Result(name="input", location="/protocols.siteStaffSelection.tiles", type="tiles")
    })
    public String save() throws NoProtocoloCompromisopaisSelectedException {
        try {
            ProtocoloCompromisopais protocoloCompromisopais =
                    protocolCRUDService.recoverProtocoloCompromisopais();

            investigadorProtocoloCentroService.save(
                    investigadorProtocoloCentro,
                    protocoloCompromisopais);

        }catch (ConcurrencyFailureException cfe){
            LOG.error("error de " + investigadorProtocoloCentro.getJustification());
            errorMessage = "Someone has just saved the same record you did";
            execute();
            return INPUT;
        }catch (InexistentProtocoloCentroException ipce){
            errorMessage = "There is not any Center Protocol asigned, create one in SitesSelection before retrying";
            execute();
            return INPUT;
        }catch (ExistentInvestigadorProtocoloCentroException eipce){
            errorMessage = "You chose an existent Primary Investigator - Site - Protocol combination. Please choose a different one";
            execute();
            return INPUT;
        }
        return SUCCESS;
    }

    private void _prepairNullSiteStaffRoles(InvestigadorProtocoloCentro ipc){
        for(RoleNameProtocoloCompromisoPais r : investigadorProtocoloCentro.getSiteStaff()){
            if(r.getRole() == null){
                Role rollOther = new Role();
                rollOther.setId(0);
                r.setRole(rollOther);
            }
        }
    }

    public List<InvestigadorProtocoloCentro> getList() {
        return list;
    }

    public void setList(List<InvestigadorProtocoloCentro> list) {
        this.list = list;
    }

    public List<Centro> getSites() {
        return sites;
    }

    public void setSites(List<Centro> sites) {
        this.sites = sites;
    }

    public List<Role> getSitesRoles() {
        List<Role> list = roleCRUDService.findSiteRole();
        Iterator<Role> it = list.iterator();
        while(it.hasNext()){
            if(it.next().getDescripcion().equals("Investigator")){
                it.remove();
            }
        }
        Role other = new Role();
        other.setId(0);
        other.setDescripcion("Other");

        list.add(other);
        return list;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public InvestigadorProtocoloCentro getInvestigadorProtocoloCentro() {
        return investigadorProtocoloCentro;
    }

    public void setInvestigadorProtocoloCentro(InvestigadorProtocoloCentro investigadorProtocoloCentro) {
        this.investigadorProtocoloCentro = investigadorProtocoloCentro;
    }

    public List<CdaMolecula> getCdaMoleculas() {
        return cdaMoleculas;
    }

    public void setCdaMoleculas(List<CdaMolecula> cdaMoleculas) {
        this.cdaMoleculas = cdaMoleculas;
    }
    public Decision[] getDecisions(){
        return Decision.values();
    }

    public Integer getSubRequiresSafetyLAF(){
        if(investigadorProtocoloCentro.isNew()){
            return -1;
        }else if(investigadorProtocoloCentro.isSubRequiresSafety()){
            return Decision.YES.getId();
        }else{
            return Decision.NO.getId();
        }
    }

    public void setSubRequiresSafetyLAF(String id) {
        Decision subRequiresSafetyLAF = Decision.values()[Integer.parseInt(id)];
        investigadorProtocoloCentro.setSubRequiresSafety(subRequiresSafetyLAF.equals(Decision.YES));
    }

    public List<Decision> getSiteStaffRequireSafety() {
        return siteStaffRequireSafety;
    }

    public void setSiteStaffRequireSafety(List<Decision> siteStaffRequireSafety) {
        this.siteStaffRequireSafety = siteStaffRequireSafety;
    }

    public Integer getHasECMemberLAF() {
        if(investigadorProtocoloCentro.getProtocoloCentro().getECMember() != null){
            return Decision.YES.getId();
        }else{
            return Decision.NO.getId();
        }
    }

    public void setHasECMemberLAF(String id) {
        Decision d = Decision.values()[Integer.parseInt(id)];
        if(d.equals(Decision.NO)){
            investigadorProtocoloCentro.getProtocoloCentro().setECMember(null);
        }
    }

    public List<Involucrado> getECMemberCandidates() {
        return ECMemberCandidates;
    }

    public void setECMemberCandidates(List<Involucrado> ECMemberCandidates) {
        this.ECMemberCandidates = ECMemberCandidates;
    }

    public enum Decision {
        YES(0,"Yes"),NO(1,"No");

        private Integer id;
        private String name;

        Decision(){
            this.id = -1;
            this.name = "";
        }

        Decision(Integer id,String name){
            this.id = id;
            this.name = name;
        }

        public String getName() {
            return this.name();
        }

        public Integer getId() {
            return this.id;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void setId(Integer id) {
            this.id = id;
        }
    }
}
